<template>
  <article class="page page-find-samefile">
    <h4 class="text-center">查找重复文件</h4>
    <form class="form row">
      <div class="col col-6">
        <fieldset>
          <legend>待查找</legend>
          <div class="fieldset-content">
            <div class="form-item-row" align="center">
              <div class="form-item-input">待查找比对的文件/文件夹</div>
              <div class="form-item-suffix" title="清空" @click="clearPendingList">
                <i class="fa fa-trash-o"></i>
              </div>
            </div>
            <div class="pending-list" @drop.prevent="pendingDrop" @dragover.prevent >
              <div class="pending-item" v-for="(v,i) in pendingsList" :key="`pending_${i}`">
                <div class="pending-item-text text-ellipsis" :title="v">{{v}}</div>
                <div v-if="findLoadingCount > 0" class="pending-item-icon">
                  <x-loading></x-loading>
                </div>
                <div v-else class="pending-item-icon" @click="deletePendingItem(i)">
                  <i class="fa fa-close"></i>
                </div>
              </div>
              <div v-if="pendingsList.length===0" class="nodata">待查找比对的文件/文件夹拖动到此处</div>
            </div>
            <div class="form-item-row" align="center">
              <x-button type="primary" block @click="findRepeat" :loading="findLoadingCount > 0">查找重复</x-button>
            </div>
          </div>
        </fieldset>
      </div>
      <div class="col col-6">
        <fieldset>
          <legend>查找结果</legend>
          <div class="fieldset-content">
            <div class="form-item-row" align="center">
              <div class="form-item-input">文件比对结果</div>
            </div>
            <div class="samefile-list">
              <div class="samefile-item" v-for="(v,i) in samefilesList" :key="`result_${i}`">
                <div class="row-flex" v-for="(item,index) in v" :key="`result_${i}_${index}`">
                  <div class="row-flex-prefix">
                    <input type="checkbox" v-model="item.checked" />
                  </div>
                  <div class="row-flex-main text-ellipsis" :title="item.filePath">{{item.filePath}}</div>
                </div>
              </div>
              <div v-show="samefilesList.length===0" class="nodata">暂无数据</div>
            </div>
            <div class="row" align="center" justify="end">
              <div class="col col-6"><x-button type="primary" block @click="selectRepeat">自动选重</x-button></div>
              <div class="col col-6"><x-button type="primary" block @click="deleteRepeat" :loading="deleteLoadingCount > 0">去重</x-button></div>
            </div>
          </div>
        </fieldset>
      </div>
    </form>
  </article>
</template>

<script>
const fs = global.require('fs')
const path = global.require('path')
// let {getFileMd5, readDir, deepCopy, delFile} = global.jstoolsNode || {}

export default {
  name: 'find-samefile',
  data () {
    return {
      pendingsList: [],
      pendingsTaskList: [],
      samefilesList: [],
      filesDict: {},
      findLoadingCount: 0,
      deleteLoadingCount: 0
    }
  },
  watch: {
    filesDict: {
      handler (n) {
        this.samefilesList = Object.values(n).filter(v => v.length > 1).map(v => {
          let _v = v.map(item => {
            return {checked: false, filePath: item}
          })
          return _v
        })
      },
      deep: true
    }
  },
  mounted () {
    // getFileMd5 = this.$sharedObject('jstoolsNode').getFileMd5
    // readDir = this.$sharedObject('jstoolsNode').readDir
    // deepCopy = this.$sharedObject('jstoolsNode').deepCopy
    // delFile = this.$sharedObject('jstoolsNode').delFile
  },
  methods: {
    // 拖拽待处理文件
    pendingDrop (e) {
      const fileList = e.dataTransfer.files
      if (!fileList) return
      for (let i = 0; i < fileList.length; i++) {
        const file = fileList[i]
        if (!this.pendingsList.includes(file.path)) {
          this.pendingsList.push(file.path)
        }
      }
    },
    // 删除条目
    deletePendingItem (index) {
      this.pendingsList.splice(index, 1)
    },
    // 清空待处理文件
    clearPendingList () {
      this.pendingsList = []
      this.pendingsTaskList = []
      this.samefilesList = []
      this.filesDict = {}
      this.findLoadingCount = 0
      this.deleteLoadingCount = 0
    },
    // 查找重复文件
    findRepeat () {
      this.pendingsTaskList = []
      this.samefilesList = []
      this.filesDict = {}
      if (this.findLoadingCount > 0) return
      this.pendingsList.forEach(v => {
        this.fileStatRecursion(v)
      })
      if (this.pendingsTaskList.length) {
        this.findLoadingCount++
        Promise.all(this.pendingsTaskList).finally(() => {
          this.findLoadingCount--
        })
      }
    },
    // 查找重复文件·递归
    fileStatRecursion (filePath) {
      if (!filePath) return
      let fileStat = fs.statSync(filePath)
      if (fileStat.isFile()) {
        this.findLoadingCount++
        let md5 = this.$sharedObject('jstoolsNode').getFileMd5(filePath)
        this.$set(this.filesDict, md5, [...(this.filesDict[md5] || []), filePath])
        this.findLoadingCount--
      } else if (fileStat.isDirectory()) {
        this.pendingsTaskList.push(
          this.$sharedObject('jstoolsNode').readDir(filePath).then((files) => {
            files.forEach(file => {
              let fp = path.join(filePath, file)
              this.fileStatRecursion(fp)
            })
          })
        )
      }
    },
    // 自动选重
    selectRepeat () {
      let samefilesList = this.$sharedObject('jstoolsNode').deepCopy(this.samefilesList)
      samefilesList.forEach(v => {
        v = v.map((item, index) => {
          item.checked = (index > 0)
        })
        return v
      })
      this.samefilesList = samefilesList
    },
    // 去重
    deleteRepeat () {
      if (this.deleteLoadingCount > 0) return
      this.deleteLoadingCount++
      this.$nextTick(() => {
        let samefilesList = this.$sharedObject('jstoolsNode').deepCopy(this.samefilesList)
        samefilesList = samefilesList.map(v => {
          let _v = []
          v.forEach(item => {
            if (item.checked) {
              this.deleteLoadingCount++
              this.$sharedObject('jstoolsNode').delFile(item.filePath)
              this.deleteLoadingCount--
            } else {
              _v.push(item)
            }
          })
          return _v
        })
        this.$toast('操作已执行！')
        this.samefilesList = samefilesList
        this.deleteLoadingCount--
      })
    },
  }
}
</script>

<style scoped lang="less">
@import "~@/assets/css/_mixins.less";
@import "~@/assets/css/_color.less";
.form-item-row {
  display: flex;
  .form-item-label {
    min-width: 4em;
    margin-right: .5em;
    text-align-last: justify;
  }
  .form-item-input {
    width: 0;
    flex-grow: 1;
    text-align: left;
  }
  .form-item-suffix {
    margin-left: .5em;
    min-width: 2em;
  }
  &[align="center"] {
    align-items: center;
  }
  &[justify="end"] {
    justify-content: flex-end;
  }
}
.page-find-samefile {
  display: flex;
  flex-direction: column;
  .form {
    flex-grow: 1;
    fieldset {
      height: 100%;
      .fieldset-content {
        height: calc(100% - 2em);
        display: flex;
        flex-direction: column;
        .pending-list, .samefile-list {
          height: 0;
          flex-grow: 1;
          margin: 1em 0;
          padding: .5em;
          border-radius: .5em;
          background-color: #fff;
          box-shadow: 0 0 .5em @bgGrey;
          overflow: hidden auto;
          position: relative;
        }
        .pending-list {
          .pending-item {
            height: 2em;
            display: flex;
            align-items: center;
            .pending-item-text {
              width: 0;
              flex-grow: 1;
            }
            .pending-item-icon {
              padding: 0 .5em;
              cursor: pointer;
            }
          }
        }
        .samefile-list {
          .samefile-item {
            border-bottom: 1px dashed @borderGrey;
            .row-flex {
              height: 2em;
              align-items: center;
            }
            &:nth-child(2n) {
              background-color: fade(@bgGrey, 50);
            }
          }
        }
      }
    }
  }
}
</style>
